//
//  UIViewController+ZCLeaks.m
//  Pods-ZCXiaoXinFenCategory_Example
//
//  Created by 张葱 on 2019/11/7.
//

#import "UIViewController+ZCLeaks.h"
#import "NSObject+ZCLeaks.h"
#import <objc/runtime.h>
/**
 目标：监听UIViewController类是否发生内存泄漏（这里只考虑push,pop的情况）
 
 思路：我们在视图控制器弹出栈，并在这个视图完全消失的时候，监听对象是否还还活着。
 
 步骤：
 1）交换视图控制器的viewWillAppear与swizzled_viewWillAppear方法，viewDidDisappear与swizzled_viewDidDisappear方法
 2）使用关联方法，获取和设置视图控制进出栈状态
 3）且在界面完全消失，并控制器的状态是出栈状态，这时，观察延时观察对象是否存活
 */

// vc - dealloc
// pop vc 存在 泄漏
// 不存在

@implementation UIViewController (ZCLeaks)
const void* const kLGHasBeenPoppedKey = &kLGHasBeenPoppedKey;

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self lg_hookOrigInstanceMenthod:@selector(viewWillAppear:) newInstanceMenthod:@selector(lg_viewWillAppear:)];
        [self lg_hookOrigInstanceMenthod:@selector(viewDidDisappear:) newInstanceMenthod:@selector(lg_viewDidDisappear:)];
        [self lg_hookOrigInstanceMenthod:@selector(dismissViewControllerAnimated:completion:) newInstanceMenthod:@selector(lg_dismissViewControllerAnimated:completion:)];
        
    });
}

// 页面进来 - key no
// 页面出去 - key - YES - lg_willDealloc 告诉析构 - dealloc
- (void)lg_viewWillAppear:(BOOL)animated{
    [self lg_viewWillAppear:animated];
    objc_setAssociatedObject(self, kLGHasBeenPoppedKey, @(NO), OBJC_ASSOCIATION_RETAIN);
}

- (void)lg_viewDidDisappear:(BOOL)animated{
    [self lg_viewDidDisappear:animated];
    
    if ([objc_getAssociatedObject(self, kLGHasBeenPoppedKey) boolValue]) {
        [self lg_willDealloc];
    }
}

- (void)lg_dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion{
    [self lg_dismissViewControllerAnimated:flag completion:completion];
    
    UIViewController *dismissedViewController = self.presentedViewController;
    if (!dismissedViewController && self.presentingViewController) {
        dismissedViewController = self;
    }
    
    if (!dismissedViewController) return;
    
    [dismissedViewController lg_willDealloc];
}


@end
